๋์ ์ผ๋ก ์ฃผ์ ๋๋ ์คํฌ๋ฆฝํธ๋ฅผ ์ํ ์ฝํ ์ธ ๋ณด์ ์ ์ฑ (CSP) ๋ ผ์ค ์์ฑ์ ๋ํ ์ข ํฉ ๊ฐ์ด๋๋ก, ํ๋ฐํธ์๋ ๋ณด์์ ๊ฐํํฉ๋๋ค.
ํ๋ฐํธ์๋ ์ฝํ ์ธ ๋ณด์ ์ ์ฑ (CSP) ๋ ผ์ค ์์ฑ: ๋์ ์คํฌ๋ฆฝํธ ๋ณด์ ๊ฐํ
์ค๋๋ ์ ์น ๊ฐ๋ฐ ํ๊ฒฝ์์ ํ๋ฐํธ์๋ ๋ณด์์ ๋ฌด์๋ณด๋ค ์ค์ํฉ๋๋ค. ์ฌ์ดํธ ๊ฐ ์คํฌ๋ฆฝํ (XSS) ๊ณต๊ฒฉ์ ์ฌ์ ํ ์ค๋ํ ์ํ์ด๋ฉฐ, ๊ฐ๋ ฅํ ์ฝํ ์ธ ๋ณด์ ์ ์ฑ (CSP)์ ํ์์ ์ธ ๋ฐฉ์ด ๋ฉ์ปค๋์ฆ์ ๋๋ค. ์ด ๊ธ์์๋ ๋์ ์ผ๋ก ์ฃผ์ ๋๋ ์คํฌ๋ฆฝํธ์ ๋ฌธ์ ์ ๊ณผ ํด๊ฒฐ์ฑ ์ ์ด์ ์ ๋ง์ถฐ, ๋ ผ์ค ๊ธฐ๋ฐ ์คํฌ๋ฆฝํธ ํ์ฉ ๋ชฉ๋ก์ ์ฌ์ฉํ์ฌ CSP๋ฅผ ๊ตฌํํ๋ ์ข ํฉ์ ์ธ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ฝํ ์ธ ๋ณด์ ์ ์ฑ (CSP)์ด๋ ๋ฌด์์ธ๊ฐ?
CSP๋ ์ฌ์ฉ์ ์์ด์ ํธ๊ฐ ํน์ ํ์ด์ง์ ๋ํด ๋ก๋ํ ์ ์๋ ๋ฆฌ์์ค๋ฅผ ์ ์ดํ ์ ์๊ฒ ํด์ฃผ๋ HTTP ์๋ต ํค๋์ ๋๋ค. ์ด๋ ๋ณธ์ง์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ์ ์ด๋ค ์์ค๊ฐ ์ ๋ขฐํ ์ ์๊ณ ์ด๋ค ์์ค๊ฐ ์ ๋ขฐํ ์ ์๋์ง ์๋ ค์ฃผ๋ ํ์ฉ ๋ชฉ๋ก(whitelist)์ ๋๋ค. ์ด๋ฅผ ํตํด ๊ณต๊ฒฉ์๊ฐ ์ฃผ์ ํ ์ ์ฑ ์คํฌ๋ฆฝํธ๋ฅผ ๋ธ๋ผ์ฐ์ ๊ฐ ์คํํ์ง ๋ชปํ๋๋ก ์ ํํ์ฌ XSS ๊ณต๊ฒฉ์ ๋ฐฉ์งํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
CSP ์ง์๋ฌธ
CSP ์ง์๋ฌธ์ ์คํฌ๋ฆฝํธ, ์คํ์ผ, ์ด๋ฏธ์ง, ๊ธ๊ผด ๋ฑ ๋ค์ํ ์ ํ์ ๋ฆฌ์์ค์ ํ์ฉ๋๋ ์์ค๋ฅผ ์ ์ํฉ๋๋ค. ์ผ๋ฐ์ ์ธ ์ง์๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- `default-src`: ํน์ ์ง์๋ฌธ์ด ์ ์๋์ง ์์ ๊ฒฝ์ฐ ๋ชจ๋ ๋ฆฌ์์ค ์ ํ์ ์ ์ฉ๋๋ ํด๋ฐฑ ์ง์๋ฌธ์ ๋๋ค.
- `script-src`: ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋์ ํ์ฉ๋๋ ์์ค๋ฅผ ์ง์ ํฉ๋๋ค.
- `style-src`: CSS ์คํ์ผ์ํธ์ ํ์ฉ๋๋ ์์ค๋ฅผ ์ง์ ํฉ๋๋ค.
- `img-src`: ์ด๋ฏธ์ง์ ํ์ฉ๋๋ ์์ค๋ฅผ ์ง์ ํฉ๋๋ค.
- `connect-src`: ๋คํธ์ํฌ ์์ฒญ(์: AJAX, WebSockets)์ ํ์ฉ๋๋ ์์ค๋ฅผ ์ง์ ํฉ๋๋ค.
- `font-src`: ๊ธ๊ผด์ ํ์ฉ๋๋ ์์ค๋ฅผ ์ง์ ํฉ๋๋ค.
- `object-src`: ํ๋ฌ๊ทธ์ธ(์: Flash)์ ํ์ฉ๋๋ ์์ค๋ฅผ ์ง์ ํฉ๋๋ค.
- `media-src`: ์ค๋์ค ๋ฐ ๋น๋์ค์ ํ์ฉ๋๋ ์์ค๋ฅผ ์ง์ ํฉ๋๋ค.
- `frame-src`: ํ๋ ์ ๋ฐ iframe์ ํ์ฉ๋๋ ์์ค๋ฅผ ์ง์ ํฉ๋๋ค.
- `base-uri`: `<base>` ์์์ ์ฌ์ฉํ ์ ์๋ URL์ ์ ํํฉ๋๋ค.
- `form-action`: ํผ์ ์ ์ถํ ์ ์๋ URL์ ์ ํํฉ๋๋ค.
๋ ผ์ค(Nonce)์ ํ
`script-src` ๋ฐ `style-src`๋ฅผ ์ฌ์ฉํ์ฌ ํน์ ๋๋ฉ์ธ์ ํ์ฉ ๋ชฉ๋ก์ ์ถ๊ฐํ๋ ๊ฒ๋ ํจ๊ณผ์ ์ผ ์ ์์ง๋ง, ์ ํ์ ์ด๊ณ ์ ์ง ๊ด๋ฆฌ๊ฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ๋ ์ ์ฐํ๊ณ ์์ ํ ์ ๊ทผ ๋ฐฉ์์ ๋ ผ์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ๋ ผ์ค(nonce, number used once)๋ ๊ฐ ์์ฒญ์ ๋ํด ์์ฑ๋๋ ์ํธํ๋ ๋์์ ๋๋ค. CSP ํค๋์ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ์ `<script>` ํ๊ทธ์ ๊ณ ์ ํ ๋ ผ์ค๋ฅผ ํฌํจํ๋ฉด, ๋ธ๋ผ์ฐ์ ๋ ์ฌ๋ฐ๋ฅธ ๋ ผ์ค ๊ฐ์ ๊ฐ์ง ์คํฌ๋ฆฝํธ๋ง ์คํํ๋๋ก ์ง์ํ ์ ์์ต๋๋ค.
๋ ผ์ค๋ฅผ ์ฌ์ฉํ CSP ํค๋ ์์:
Content-Security-Policy: default-src 'self'; script-src 'nonce-{{nonce}}'
๋ ผ์ค๋ฅผ ์ฌ์ฉํ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ ํ๊ทธ ์์:
<script nonce="{{nonce}}">console.log('Hello, world!');</script>
๋ ผ์ค ์์ฑ: ํต์ฌ ๊ฐ๋
๋ ผ์ค๋ฅผ ์์ฑํ๊ณ ์ ์ฉํ๋ ๊ณผ์ ์ ์ผ๋ฐ์ ์ผ๋ก ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฆ ๋๋ค:
- ์๋ฒ ์ธก ์์ฑ: ๋ค์ด์ค๋ ๊ฐ ์์ฒญ์ ๋ํด ์๋ฒ์์ ์ํธํ์ ์ผ๋ก ์์ ํ ๋์ ๋ ผ์ค ๊ฐ์ ์์ฑํฉ๋๋ค.
- ํค๋ ์ฝ์ : ์์ฑ๋ ๋ ผ์ค๋ฅผ `Content-Security-Policy` ํค๋์ ํฌํจ์ํค๊ณ , `{{nonce}}`๋ฅผ ์ค์ ๊ฐ์ผ๋ก ๋์ฒดํฉ๋๋ค.
- ์คํฌ๋ฆฝํธ ํ๊ทธ ์ฝ์ : ์คํ์ ํ์ฉํ๋ ค๋ ๊ฐ ์ธ๋ผ์ธ `<script>` ํ๊ทธ์ `nonce` ์์ฑ์ ๋์ผํ ๋ ผ์ค ๊ฐ์ ์ฃผ์ ํฉ๋๋ค.
๋์ ์ผ๋ก ์ฃผ์ ๋๋ ์คํฌ๋ฆฝํธ์ ๋ฌธ์ ์
๋ ผ์ค๋ ์ ์ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ์๋ ํจ๊ณผ์ ์ด์ง๋ง, ๋์ ์ผ๋ก ์ฃผ์ ๋๋ ์คํฌ๋ฆฝํธ๋ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํฉ๋๋ค. ๋์ ์ผ๋ก ์ฃผ์ ๋๋ ์คํฌ๋ฆฝํธ๋ ์ด๊ธฐ ํ์ด์ง ๋ก๋ ํ, ์ข ์ข ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋์ ์ํด DOM์ ์ถ๊ฐ๋๋ ์คํฌ๋ฆฝํธ์ ๋๋ค. ์ด๊ธฐ ์์ฒญ์ CSP ํค๋๋ฅผ ์ค์ ํ๋ ๊ฒ๋ง์ผ๋ก๋ ์ด๋ ๊ฒ ๋์ ์ผ๋ก ์ถ๊ฐ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
๋ค์๊ณผ ๊ฐ์ ์๋๋ฆฌ์ค๋ฅผ ์๊ฐํด ๋ณด์ญ์์ค: ```javascript function injectScript(url) { const script = document.createElement('script'); script.src = url; document.head.appendChild(script); } injectScript('https://example.com/script.js'); ``` ๋ง์ฝ `https://example.com/script.js`๊ฐ CSP์ ๋ช ์์ ์ผ๋ก ํ์ฉ๋์ง ์์๊ฑฐ๋ ์ฌ๋ฐ๋ฅธ ๋ ผ์ค๋ฅผ ๊ฐ์ง๊ณ ์์ง ์๋ค๋ฉด, ์ด๊ธฐ ํ์ด์ง ๋ก๋ ์ ์ ํจํ CSP์ ๋ ผ์ค๊ฐ ์์๋๋ผ๋ ๋ธ๋ผ์ฐ์ ๋ ์คํ์ ์ฐจ๋จํ ๊ฒ์ ๋๋ค. ์ด๋ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ฆฌ์์ค๊ฐ ์์ฒญ๋๊ฑฐ๋ ์คํ๋๋ ์์ ์๋ง CSP๋ฅผ ํ๊ฐํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋์ ์ผ๋ก ์ฃผ์ ๋๋ ์คํฌ๋ฆฝํธ๋ฅผ ์ํ ํด๊ฒฐ์ฑ
CSP์ ๋ ผ์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋์ ์ผ๋ก ์ฃผ์ ๋๋ ์คํฌ๋ฆฝํธ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ช ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์์ด ์์ต๋๋ค:
1. ์๋ฒ ์ธก ๋ ๋๋ง(SSR) ๋๋ ์ฌ์ ๋ ๋๋ง
๊ฐ๋ฅํ๋ค๋ฉด ์คํฌ๋ฆฝํธ ์ฃผ์ ๋ก์ง์ ์๋ฒ ์ธก ๋ ๋๋ง(SSR) ํ๋ก์ธ์ค๋ก ์ฎ๊ธฐ๊ฑฐ๋ ์ฌ์ ๋ ๋๋ง ๊ธฐ์ ์ ์ฌ์ฉํ์ญ์์ค. ์ด๋ฅผ ํตํด ํ์ด์ง๊ฐ ํด๋ผ์ด์ธํธ๋ก ์ ์ก๋๊ธฐ ์ ์ ์ฌ๋ฐ๋ฅธ ๋ ผ์ค๋ฅผ ๊ฐ์ง ํ์ํ `<script>` ํ๊ทธ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. Next.js(React), Nuxt.js(Vue), SvelteKit๊ณผ ๊ฐ์ ํ๋ ์์ํฌ๋ ์๋ฒ ์ธก ๋ ๋๋ง์ ๋ฐ์ด๋๋ฉฐ ์ด ๊ณผ์ ์ ๋จ์ํํ ์ ์์ต๋๋ค.
์์ (Next.js):
```javascript function MyComponent() { const nonce = getCspNonce(); // ๋ ผ์ค๋ฅผ ๊ฐ์ ธ์ค๋ ํจ์ return ( <script nonce={nonce} src="/path/to/script.js"></script> ); } export default MyComponent; ```2. ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ ๋ ผ์ค ์ฃผ์
์ด ๋ฐฉ๋ฒ์ ์๋ฒ์์ ๋ ผ์ค๋ฅผ ์์ฑํ์ฌ ํด๋ผ์ด์ธํธ ์ธก ์๋ฐ์คํฌ๋ฆฝํธ์์ ์ฌ์ฉํ ์ ์๋๋ก ํ ๋ค์, ๋์ ์ผ๋ก ์์ฑ๋ ์คํฌ๋ฆฝํธ ์์์ `nonce` ์์ฑ์ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์ค์ ํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค.
๋จ๊ณ:
- ๋ ผ์ค ๋ ธ์ถ: ์ด๊ธฐ HTML์ ๋ ผ์ค ๊ฐ์ ์ ์ญ ๋ณ์๋ ์์์ ๋ฐ์ดํฐ ์์ฑ์ผ๋ก ํฌํจ์ํต๋๋ค. ์ฝ๊ฒ ์กฐ์๋ ์ ์์ผ๋ฏ๋ก ๋ฌธ์์ด์ ์ง์ ํฌํจํ๋ ๊ฒ์ ํผํ์ญ์์ค. ์์ ํ ์ธ์ฝ๋ฉ ๋ฉ์ปค๋์ฆ ์ฌ์ฉ์ ๊ณ ๋ คํ์ญ์์ค.
- ๋ ผ์ค ๊ฒ์: ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋์์ ์ ์ฅ๋ ์์น๋ก๋ถํฐ ๋ ผ์ค ๊ฐ์ ๊ฒ์ํฉ๋๋ค.
- Nonce ์์ฑ ์ค์ : ์คํฌ๋ฆฝํธ ์์๋ฅผ DOM์ ์ถ๊ฐํ๊ธฐ ์ ์ `nonce` ์์ฑ์ ๊ฒ์๋ ๊ฐ์ผ๋ก ์ค์ ํฉ๋๋ค.
์์:
์๋ฒ ์ธก (์: Python/Flask์์ Jinja2 ์ฌ์ฉ):
```html <div id="csp-nonce" data-nonce="{{ nonce }}"></div> ```ํด๋ผ์ด์ธํธ ์ธก ์๋ฐ์คํฌ๋ฆฝํธ:
```javascript function injectScript(url) { const nonceElement = document.getElementById('csp-nonce'); const nonce = nonceElement ? nonceElement.dataset.nonce : null; if (!nonce) { console.error('CSP nonce not found!'); return; } const script = document.createElement('script'); script.src = url; script.nonce = nonce; document.head.appendChild(script); } injectScript('https://example.com/script.js'); ```์ค์ ๊ณ ๋ ค์ฌํญ:
- ์์ ํ ์ ์ฅ: ๋ ผ์ค๋ฅผ ๋ ธ์ถํ๋ ๋ฐฉ๋ฒ์ ์ฃผ์ํ์ญ์์ค. HTML ์์ค์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ์์ด์ ์ง์ ํฌํจํ๋ ๊ฒ์ ์ทจ์ฝํ ์ ์์ผ๋ฏ๋ก ํผํด์ผ ํฉ๋๋ค. ์์์ ๋ฐ์ดํฐ ์์ฑ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ผ๋ก ๋ ์์ ํ ์ ๊ทผ ๋ฐฉ์์ ๋๋ค.
- ์ค๋ฅ ์ฒ๋ฆฌ: ๊ตฌ์ฑ ์ค๋ฅ ๋ฑ์ผ๋ก ์ธํด ๋ ผ์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒฝ์ฐ๋ฅผ ์ ์์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ํฌํจ์ํค์ญ์์ค. ์คํฌ๋ฆฝํธ ์ฃผ์ ์ ๊ฑด๋๋ฐ๊ฑฐ๋ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๊ธฐ๋กํ๋๋ก ์ ํํ ์ ์์ต๋๋ค.
3. 'unsafe-inline' ์ฌ์ฉ (๊ถ์ฅํ์ง ์์)
์ต์ ์ ๋ณด์์ ์ํด ๊ถ์ฅ๋์ง๋ ์์ง๋ง, `script-src` ๋ฐ `style-src` CSP ์ง์๋ฌธ์ `'unsafe-inline'` ์ง์๋ฌธ์ ์ฌ์ฉํ๋ฉด ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ์ ์คํ์ผ์ด ๋ ผ์ค ์์ด ์คํ๋ ์ ์์ต๋๋ค. ์ด๋ ์ฌ์ค์ ๋ ผ์ค๊ฐ ์ ๊ณตํ๋ ๋ณดํธ๋ฅผ ์ฐํํ๊ณ CSP๋ฅผ ํฌ๊ฒ ์ฝํ์ํต๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ์ตํ์ ์๋จ์ผ๋ก๋ง, ๊ทธ๋ฆฌ๊ณ ๊ทน๋์ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ฌ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
๊ถ์ฅํ์ง ์๋ ์ด์ :
๋ชจ๋ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํจ์ผ๋ก์จ ์ ํ๋ฆฌ์ผ์ด์ ์ XSS ๊ณต๊ฒฉ์ ๋ ธ์ถ์ํค๊ฒ ๋ฉ๋๋ค. ๊ณต๊ฒฉ์๋ ํ์ด์ง์ ์ ์ฑ ์คํฌ๋ฆฝํธ๋ฅผ ์ฃผ์ ํ ์ ์์ผ๋ฉฐ, CSP๊ฐ ๋ชจ๋ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ธ๋ผ์ฐ์ ๋ ์ด๋ฅผ ์คํํ ๊ฒ์ ๋๋ค.
4. ์คํฌ๋ฆฝํธ ํด์
๋ ผ์ค ๋์ ์คํฌ๋ฆฝํธ ํด์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ ์คํฌ๋ฆฝํธ ๋ด์ฉ์ SHA-256, SHA-384 ๋๋ SHA-512 ํด์๋ฅผ ๊ณ์ฐํ๊ณ `script-src` ์ง์๋ฌธ์ ํฌํจ์ํค๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ๋ ํด์๊ฐ ์ง์ ๋ ๊ฐ๊ณผ ์ผ์นํ๋ ์คํฌ๋ฆฝํธ๋ง ์คํํฉ๋๋ค.
์์:
`script.js`์ ๋ด์ฉ์ด `console.log('Hello, world!');`์ด๊ณ , ๊ทธ SHA-256 ํด์๊ฐ `sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=`๋ผ๊ณ ๊ฐ์ ํ๋ฉด, CSP ํค๋๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ ๋๋ค:
Content-Security-Policy: default-src 'self'; script-src 'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='
์ฅ์ :
- ์ ํํ ์ ์ด: ํด์๊ฐ ์ผ์นํ๋ ํน์ ์คํฌ๋ฆฝํธ๋ง ์คํํ๋๋ก ํ์ฉํฉ๋๋ค.
- ์ ์ ์คํฌ๋ฆฝํธ์ ์ ํฉ: ์คํฌ๋ฆฝํธ ๋ด์ฉ์ด ์ฌ์ ์ ์๋ ค์ ธ ์๊ณ ์์ฃผ ๋ณ๊ฒฝ๋์ง ์์ ๋ ์ ์๋ํฉ๋๋ค.
๋จ์ :
- ์ ์ง ๊ด๋ฆฌ ๋ถ๋ด: ์คํฌ๋ฆฝํธ ๋ด์ฉ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ํด์๋ฅผ ๋ค์ ๊ณ์ฐํ๊ณ CSP ํค๋๋ฅผ ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค. ์ด๋ ๋์ ์คํฌ๋ฆฝํธ๋ ์์ฃผ ์ ๋ฐ์ดํธ๋๋ ์คํฌ๋ฆฝํธ์ ๊ฒฝ์ฐ ๋ฒ๊ฑฐ๋ก์ธ ์ ์์ต๋๋ค.
- ๋์ ์คํฌ๋ฆฝํธ์ ๋ํ ์ด๋ ค์: ๋์ ์คํฌ๋ฆฝํธ ๋ด์ฉ์ ์ฆ์์์ ํด์ฑํ๋ ๊ฒ์ ๋ณต์กํ ์ ์์ผ๋ฉฐ ์ฑ๋ฅ ์ ํ๋ฅผ ์ ๋ฐํ ์ ์์ต๋๋ค.
CSP ๋ ผ์ค ์์ฑ์ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
- ์ํธํ์ ์ผ๋ก ์์ ํ ๋์ ์์ฑ๊ธฐ ์ฌ์ฉ: ๊ณต๊ฒฉ์๊ฐ ๋ ผ์ค๋ฅผ ์์ธกํ ์ ์๋๋ก ๋ ผ์ค ์์ฑ ๊ณผ์ ์์ ์ํธํ์ ์ผ๋ก ์์ ํ ๋์ ์์ฑ๊ธฐ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
- ๊ฐ ์์ฒญ๋ง๋ค ์๋ก์ด ๋ ผ์ค ์์ฑ: ๋ค๋ฅธ ์์ฒญ ๊ฐ์ ๋ ผ์ค๋ฅผ ์ฌ์ฌ์ฉํด์๋ ์ ๋ฉ๋๋ค. ๊ฐ ํ์ด์ง ๋ก๋๋ง๋ค ๊ณ ์ ํ ๋ ผ์ค ๊ฐ์ ๊ฐ์ ธ์ผ ํฉ๋๋ค.
- ์์ ํ ๋ ผ์ค ์ ์ฅ ๋ฐ ์ ์ก: ๋ ผ์ค๊ฐ ๊ฐ๋ก์ฑ์ง๊ฑฐ๋ ์กฐ์๋์ง ์๋๋ก ๋ณดํธํ์ญ์์ค. ์๋ฒ์ ํด๋ผ์ด์ธํธ ๊ฐ์ ํต์ ์ ์ํธํํ๊ธฐ ์ํด HTTPS๋ฅผ ์ฌ์ฉํ์ญ์์ค.
- ์๋ฒ์์ ๋ ผ์ค ๊ฒ์ฆ: (ํด๋นํ๋ ๊ฒฝ์ฐ) ์คํฌ๋ฆฝํธ ์คํ์ด ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋น๋กฏ๋์๋์ง ํ์ธํด์ผ ํ๋ ์๋๋ฆฌ์ค(์: ๋ถ์ ๋๋ ์ถ์ )์์๋ ์คํฌ๋ฆฝํธ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๋ณด๋ผ ๋ ์๋ฒ ์ธก์์ ๋ ผ์ค๋ฅผ ๊ฒ์ฆํ ์ ์์ต๋๋ค.
- ์ ๊ธฐ์ ์ธ CSP ๊ฒํ ๋ฐ ์ ๋ฐ์ดํธ: CSP๋ 'ํ ๋ฒ ์ค์ ํ๊ณ ์์ด๋ฒ๋ฆฌ๋' ํด๊ฒฐ์ฑ ์ด ์๋๋๋ค. ์๋ก์ด ์ํ๊ณผ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณ๊ฒฝ ์ฌํญ์ ๋์ฒํ๊ธฐ ์ํด ์ ๊ธฐ์ ์ผ๋ก CSP๋ฅผ ๊ฒํ ํ๊ณ ์ ๋ฐ์ดํธํ์ญ์์ค. ์๋ฐ ์ฌํญ์ ๋ชจ๋ํฐ๋งํ๊ณ ์ ์ฌ์ ์ธ ๋ณด์ ๋ฌธ์ ๋ฅผ ์๋ณํ๊ธฐ ์ํด CSP ๋ณด๊ณ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค.
- CSP ๋ณด๊ณ ๋๊ตฌ ์ฌ์ฉ: Report-URI๋ Sentry์ ๊ฐ์ ๋๊ตฌ๋ CSP ์๋ฐ์ ๋ชจ๋ํฐ๋งํ๊ณ CSP ๊ตฌ์ฑ์ ์ ์ฌ์ ์ธ ๋ฌธ์ ๋ฅผ ์๋ณํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค. ์ด๋ฌํ ๋๊ตฌ๋ ์ด๋ค ์คํฌ๋ฆฝํธ๊ฐ ์ ์ฐจ๋จ๋๊ณ ์๋์ง์ ๋ํ ๊ท์คํ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํ์ฌ CSP๋ฅผ ๊ฐ์ ํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณด์์ ํฅ์์ํฌ ์ ์๋๋ก ํฉ๋๋ค.
- ๋ณด๊ณ ์ ์ฉ ์ ์ฑ ์ผ๋ก ์์: CSP๋ฅผ ์ํํ๊ธฐ ์ ์ ๋ณด๊ณ ์ ์ฉ ์ ์ฑ ์ผ๋ก ์์ํ์ญ์์ค. ์ด๋ฅผ ํตํด ์ค์ ๋ก ๋ฆฌ์์ค๋ฅผ ์ฐจ๋จํ์ง ์๊ณ ์ ์ฑ ์ ์ํฅ์ ๋ชจ๋ํฐ๋งํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ํ์ ์ด ์๊ธฐ๋ฉด ์ ์ฐจ์ ์ผ๋ก ์ ์ฑ ์ ๊ฐํํ ์ ์์ต๋๋ค. `Content-Security-Policy-Report-Only` ํค๋๋ ์ด ๋ชจ๋๋ฅผ ํ์ฑํํฉ๋๋ค.
CSP ๊ตฌํ์ ์ํ ๊ธ๋ก๋ฒ ๊ณ ๋ ค์ฌํญ
์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ๋์์ผ๋ก CSP๋ฅผ ๊ตฌํํ ๋ ๋ค์ ์ฌํญ์ ๊ณ ๋ คํ์ญ์์ค:
- ๋ค๊ตญ์ด ๋๋ฉ์ธ ์ด๋ฆ(IDN): CSP ์ ์ฑ ์ด IDN์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋์ง ํ์ธํ์ญ์์ค. ๋ธ๋ผ์ฐ์ ๋ IDN์ ๋ค๋ฅด๊ฒ ์ทจ๊ธํ ์ ์์ผ๋ฏ๋ก ์๊ธฐ์น ์์ ์ฐจ๋จ์ ํผํ๊ธฐ ์ํด ๋ค์ํ IDN์ผ๋ก CSP๋ฅผ ํ ์คํธํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
- ์ฝํ ์ธ ์ ์ก ๋คํธ์ํฌ(CDN): CDN์ ์ฌ์ฉํ์ฌ ์คํฌ๋ฆฝํธ์ ์คํ์ผ์ ์ ๊ณตํ๋ ๊ฒฝ์ฐ `script-src` ๋ฐ `style-src` ์ง์๋ฌธ์ CDN ๋๋ฉ์ธ์ ํฌํจํด์ผ ํฉ๋๋ค. ์์ผ๋์นด๋ ๋๋ฉ์ธ(์: `*.cdn.example.com`)์ ๋ณด์ ์ํ์ ์ด๋ํ ์ ์์ผ๋ฏ๋ก ์ฌ์ฉ์ ์ ์ํ์ญ์์ค.
- ์ง์ญ ๊ท์ : CSP ๊ตฌํ์ ์ํฅ์ ์ค ์ ์๋ ์ง์ญ ๊ท์ ์ ์์งํ์ญ์์ค. ์๋ฅผ ๋ค์ด, ์ผ๋ถ ๊ตญ๊ฐ์์๋ ๋ฐ์ดํฐ ํ์งํ ๋๋ ๊ฐ์ธ ์ ๋ณด ๋ณดํธ์ ๋ํ ํน์ ์๊ตฌ ์ฌํญ์ด ์์ ์ ์์ผ๋ฉฐ, ์ด๋ CDN ๋๋ ๊ธฐํ ํ์ฌ ์๋น์ค ์ ํ์ ์ํฅ์ ์ค ์ ์์ต๋๋ค.
- ๋ฒ์ญ ๋ฐ ํ์งํ: ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ฌ๋ฌ ์ธ์ด๋ฅผ ์ง์ํ๋ ๊ฒฝ์ฐ CSP ์ ์ฑ ์ด ๋ชจ๋ ์ธ์ด์ ํธํ๋๋์ง ํ์ธํ์ญ์์ค. ์๋ฅผ ๋ค์ด, ํ์งํ๋ฅผ ์ํด ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ฌ๋ฐ๋ฅธ ๋ ผ์ค๋ฅผ ๊ฐ์ง๊ณ ์๊ฑฐ๋ CSP์์ ํ์ฉ ๋ชฉ๋ก์ ํฌํจ๋์ด ์๋์ง ํ์ธํด์ผ ํฉ๋๋ค.
์์ ์๋๋ฆฌ์ค: ๋ค๊ตญ์ด ์ด์ปค๋จธ์ค ์น์ฌ์ดํธ
A/B ํ ์คํธ, ์ฌ์ฉ์ ์ถ์ ๋ฐ ๊ฐ์ธํ๋ฅผ ์ํด ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ๋์ ์ผ๋ก ์ฃผ์ ํ๋ ๋ค๊ตญ์ด ์ด์ปค๋จธ์ค ์น์ฌ์ดํธ๋ฅผ ์๊ฐํด ๋ณด์ญ์์ค.
๊ณผ์ :
- ๋์ ์คํฌ๋ฆฝํธ ์ฃผ์ : A/B ํ ์คํธ ํ๋ ์์ํฌ๋ ์ข ์ข ์คํ ๋ณํ์ ์ ์ดํ๊ธฐ ์ํด ์คํฌ๋ฆฝํธ๋ฅผ ๋์ ์ผ๋ก ์ฃผ์ ํฉ๋๋ค.
- ํ์ฌ ์คํฌ๋ฆฝํธ: ์ฌ์ฉ์ ์ถ์ ๋ฐ ๊ฐ์ธํ๋ ๋ค๋ฅธ ๋๋ฉ์ธ์์ ํธ์คํ ๋๋ ํ์ฌ ์คํฌ๋ฆฝํธ์ ์์กดํ ์ ์์ต๋๋ค.
- ์ธ์ด๋ณ ๋ก์ง: ์ผ๋ถ ์ธ์ด๋ณ ๋ก์ง์ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํ๋ ์ ์์ต๋๋ค.
ํด๊ฒฐ์ฑ :
- ๋ ผ์ค ๊ธฐ๋ฐ CSP ๊ตฌํ: XSS ๊ณต๊ฒฉ์ ๋ํ ์ฃผ์ ๋ฐฉ์ด ์๋จ์ผ๋ก ๋ ผ์ค ๊ธฐ๋ฐ CSP๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- A/B ํ ์คํธ ์คํฌ๋ฆฝํธ๋ฅผ ์ํ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ ๋ ผ์ค ์ฃผ์ : ์์์ ์ค๋ช ํ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ ๋ ผ์ค ์ฃผ์ ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ๋์ ์ผ๋ก ์์ฑ๋ A/B ํ ์คํธ ์คํฌ๋ฆฝํธ ์์์ ๋ ผ์ค๋ฅผ ์ฃผ์ ํฉ๋๋ค.
- ํน์ ํ์ฌ ๋๋ฉ์ธ ํ์ฉ ๋ชฉ๋ก ์ถ๊ฐ: ์ ๋ขฐํ ์ ์๋ ํ์ฌ ์คํฌ๋ฆฝํธ์ ๋๋ฉ์ธ์ `script-src` ์ง์๋ฌธ์ ์ ์คํ๊ฒ ํ์ฉ ๋ชฉ๋ก์ ์ถ๊ฐํฉ๋๋ค. ์ ๋์ ์ผ๋ก ํ์ํ ๊ฒฝ์ฐ๊ฐ ์๋๋ฉด ์์ผ๋์นด๋ ๋๋ฉ์ธ ์ฌ์ฉ์ ํผํฉ๋๋ค.
- ์ธ์ด๋ณ ๋ก์ง์ ์ํ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ ํด์ฑ: ๊ฐ๋ฅํ๋ค๋ฉด ์ธ์ด๋ณ ๋ก์ง์ ๋ณ๋์ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ๋ก ์ฎ๊ธฐ๊ณ ์คํฌ๋ฆฝํธ ํด์๋ฅผ ์ฌ์ฉํ์ฌ ํ์ฉ ๋ชฉ๋ก์ ์ถ๊ฐํฉ๋๋ค. ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๊ฐ ๋ถ๊ฐํผํ ๊ฒฝ์ฐ, ์คํฌ๋ฆฝํธ ํด์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋ณ์ ์ผ๋ก ํ์ฉ ๋ชฉ๋ก์ ์ถ๊ฐํฉ๋๋ค.
- CSP ๋ณด๊ณ : CSP ๋ณด๊ณ ๋ฅผ ๊ตฌํํ์ฌ ์๋ฐ ์ฌํญ์ ๋ชจ๋ํฐ๋งํ๊ณ ์๊ธฐ์น ์์ ์คํฌ๋ฆฝํธ ์ฐจ๋จ์ ์๋ณํฉ๋๋ค.
๊ฒฐ๋ก
CSP ๋ ผ์ค๋ก ๋์ ์ผ๋ก ์ฃผ์ ๋๋ ์คํฌ๋ฆฝํธ๋ฅผ ๋ณดํธํ๋ ค๋ฉด ์ ์คํ๊ณ ์ ๊ณํ๋ ์ ๊ทผ ๋ฐฉ์์ด ํ์ํฉ๋๋ค. ๋จ์ํ ๋๋ฉ์ธ์ ํ์ฉ ๋ชฉ๋ก์ ์ถ๊ฐํ๋ ๊ฒ๋ณด๋ค ๋ณต์กํ ์ ์์ง๋ง, ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณด์ ์ํ๋ฅผ ํฌ๊ฒ ํฅ์์ํต๋๋ค. ์ด ๊ธ์์ ์ค๋ช ํ ๋ฌธ์ ์ ์ ์ดํดํ๊ณ ํด๊ฒฐ์ฑ ์ ๊ตฌํํจ์ผ๋ก์จ ํ๋ฐํธ์๋๋ฅผ XSS ๊ณต๊ฒฉ์ผ๋ก๋ถํฐ ํจ๊ณผ์ ์ผ๋ก ๋ณดํธํ๊ณ ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํด ๋ ์์ ํ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค. ํญ์ ๋ณด์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ฐ์ ์ํ๊ณ ์๋ก์ด ์ํ์ ์์ ๋๊ฐ๊ธฐ ์ํด ์ ๊ธฐ์ ์ผ๋ก CSP๋ฅผ ๊ฒํ ํ๊ณ ์ ๋ฐ์ดํธํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค.
์ด ๊ฐ์ด๋์ ์ค๋ช ๋ ์์น๊ณผ ๊ธฐ์ ์ ๋ฐ๋ฅด๋ฉด ๋์ ์ผ๋ก ์ฃผ์ ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ๋ฉด์๋ ์น์ฌ์ดํธ๋ฅผ XSS ๊ณต๊ฒฉ์ผ๋ก๋ถํฐ ๋ณดํธํ๋ ๊ฐ๋ ฅํ๊ณ ํจ๊ณผ์ ์ธ CSP๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. CSP๊ฐ ์์๋๋ก ์๋ํ๊ณ ํฉ๋ฒ์ ์ธ ๋ฆฌ์์ค๋ฅผ ์ฐจ๋จํ์ง ์๋์ง ํ์ธํ๊ธฐ ์ํด ์ฒ ์ ํ๊ฒ ํ ์คํธํ๊ณ ์ ๊ธฐ์ ์ผ๋ก ๋ชจ๋ํฐ๋งํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค.